home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Cream of the Crop 26
/
Cream of the Crop 26.iso
/
program
/
qlib205.zip
/
QLIB.ZIP
/
SRC
/
QLIB
/
SPRINT.ASM
< prev
next >
Wrap
Assembly Source File
|
1997-01-20
|
9KB
|
473 lines
include qlib.inc ;setup
include dos.inc
include string.inc
include conio.inc
include stdlib.inc
.data?
align 4
_bak dd ?
_width dd ?
_pad dd ? ;used with %s when width is used
_dec dd ? ;width after . (%f)
tempstr db 64 dup(?)
_pos db ? ;flag : use positive sign on signed #'s
_zero db ? ;flag : do not remove leading zeros
_dot db ? ;flag : . used with %f
_decu db ? ;flag : is _dec used?
_typ db ? ;type : the char after the % (ie: d,x,X,c,s,f,etc.)
epos dd ? ;used for %f and %e
esiz dd ?
.code
decode_per proc private uses ecx
; in : esi=string (right after %)
; : ebx=varargs
; out : eax=# bytes needed
; : _typ=char (c,s,d...)
; : _width=byte (max=9999)
; : _zero = T/F
; : _pos = T/F
local m:byte
mov m,0
mov _pos,0
mov _zero,0
mov _width,0
mov _dot,0
mov _dec,0 ;decimal width for decimals (BC uses 6 which is dumb)
mov _decu,0
mov _bak,esi
@@:
lodsb
gotit:
.if al=='.'
.if _dot
jmp bad
.endif
inc _dot
mov m,0
jmp @b
.endif
.if (al=='0') && (!_zero) && (!_width) && (!_dot)
inc _zero
jmp @b
.endif
.if (al=='+')
.if _pos
jmp bad
.endif
inc _pos
jmp @b
.endif
.if (al>='0') && (al<='9')
.if _dot
mov _decu,1
.if m > 5
jmp @b ;ignore # (it's large enough)
.endif
mov ecx,_dec
imul ecx,10
inc m
sub al,'0'
xor ah,ah
add cx,ax
mov _dec,ecx
jmp @b
.endif
.if m > 5
jmp @b ;ignore # (it's large enough)
.endif
mov ecx,_width
imul ecx,10
inc m
sub al,'0'
xor ah,ah
add cx,ax
mov _width,ecx
jmp @b
.endif
.if al=='f'
mov _typ,al
mov eax,64
add ebx,4 ;add an aditional 4bytes cause floats are 64bit (double!)
jmp done
.endif
.if al=='e'
mov _typ,al
mov eax,64
add ebx,4 ;add an aditional 4bytes cause floats are 64bit (double!)
jmp done
.endif
.if (_dot)
jmp bad
.endif
.if al=='b'
mov _typ,al ;binary
mov eax,33
jmp done
.endif
.if al=='o'
mov _typ,al ;octal
mov eax,17
jmp done
.endif
.if al=='x'
mov _typ,al ;hex
mov eax,9
jmp done
.endif
.if al=='X'
mov _typ,al ;HEX
mov eax,9
jmp done
.endif
.if al=='u'
mov _typ,al ;unsigned
mov eax,11
jmp done
.endif
.if al=='d' || al=='i' ;signed
mov _typ,al
mov eax,12
jmp done
.endif
.if (_zero) || (_pos) || (_dot)
jmp bad
.endif
.if al=='s' ;string
mov _typ,al
mov eax,[ebx]
callp strlen,eax
.if eax < _width
mov ecx,_width
mov _pad,ecx
sub _pad,eax
mov eax,ecx
.endif
jmp done
.elseif al=='c'
mov _typ,al
mov eax,1
jmp done
.endif
jmp bad
done:
.if _width > eax ;make sure to return largest #
mov eax,_width
.endif
add ebx,4
ret
bad:
mov esi,_bak
mov _typ,0
xor eax,eax
ret
decode_per endp
_printf_siz proc,str1:dword,args:vararg
;calculate maximum RAM required for string when all % expanded.
; out : eax = max size needed
lea eax,args
callp _vprintf_siz,str1,eax
ret
_printf_siz endp
_vprintf_siz proc,str1:dword,args:dword
local siz:dword
pushad
mov esi,str1
mov ebx,args
mov siz,0
@@:
cmp byte ptr[esi],0
jz @f
cmp byte ptr[esi],'%'
jz @@per
inc siz
inc esi
jmp @b
@@per:
inc esi
cmp byte ptr[esi],'%'
jnz @@per2
inc esi
inc siz ;just one % will go out
jmp @b
@@per2:
call decode_per
.if !eax
inc siz ;for the % (w/ error)
.elseif
add siz,eax
.endif
jmp @b
@@:
inc siz ;for the 0
popad
mov eax,siz
ret
_vprintf_siz endp
;prints into string
sprintf proc,buf:dword,str1:dword,args:vararg
lea eax,args
callp vsprintf,buf,str1,eax
ret
sprintf endp
vsprintf proc,buf:dword,str1:dword,args:dword
;prints C type string from src => dest
; % [+][0][width][S] type
; type=[d],[o],[x],[X],[b],[c],[s],[%],[f]
; +=use + when printing signed #'s
; 0=keep all leading zeros
; S=signed modifier (error if used with 'c' or 's')
; x,X=hex output (as in C)
; b=binary output
; d=decimal output
; c=char
; s=string
; f=double (DO NOT USE FLOAT)
; NO LOCALS ALLOWED
; FIX : v2.00 Beta #2 : this was not preserving regs!
pushad
mov esi,str1
mov edi,buf
mov ebx,args
mov ebp,ebx
@@top:
mov al,[esi]
cmp al,0
jz __end
cmp al,'%'
jz @@per
@@per1:
movsb
jmp @@top
@@per: ; % is use
inc esi
mov al,[esi]
cmp al,'%'
jz @@per1 ;2 % = 1 %
mov ebx,ebp
call decode_per
mov al,_typ
cmp al,0
jz __end
cmp al,'u'
jz @@peru
cmp al,'i'
jz @@perd
cmp al,'d'
jz @@perd
cmp al,'x'
jz @@perx
cmp al,'X'
jz @@perxc
cmp al,'c'
jz @@perc
cmp al,'o'
jz @@pero
cmp al,'b'
jz @@perb
cmp al,'e'
jz @@perf
cmp al,'f'
jz @@perf
;must be 's'
.if _width && _pad
mov al,32
mov ecx,_pad
rep stosb
.endif
callp strcpy,edi,[ebp]
callp strlen,[ebp]
add edi,eax
add ebp,4
jmp @@top
@@perf:
.if _dec > 40
mov _dec,40 ;no more than this is needed
.endif
.if !_decu
mov _dec,6
.endif
.if al=='f'
callp ftoa,REAL8 PTR[ebp],offset tempstr,_dec
.else ;'e'
callp etoa,REAL8 PTR[ebp],offset tempstr,_dec
.endif
jmp addfstr
@@perb:
callp num2str,[ebp],offset tempstr,2
jmp addstr
@@pero:
callp num2str,[ebp],offset tempstr,8
jmp addstr
@@perd:
callp num2strs,[ebp],offset tempstr,10 ;signed!
jmp addstr
@@peru:
callp num2str,[ebp],offset tempstr,10 ;unsigned!
jmp addstr
@@perx: ;hex w/ lower case
callp num2str,[ebp],offset tempstr,16
jmp addstr
@@perxc: ;hex w/capitals
callp num2strc,[ebp],offset tempstr,16
jmp addstr
@@perc:
mov al,[ebp]
mov [edi],al
inc edi
add ebp,4 ;no byte pushes possible
jmp @@top
__end:
mov byte ptr[edi],0
popad
xor eax,eax
ret
addstr:
add ebp,4 ;move to next var.
;copy tempstr to edi based on _*
push esi
mov esi,offset tempstr
.if (_pos) && (bptr[esi]!='-')
mov eax,esi
inc eax
callp memcpy,eax,esi,sizeof tempstr - 1
mov bptr[esi],'+'
.endif
callp strlen,esi
mov ebx,eax
.if eax < _width
mov ecx,_width
sub ecx,eax
mov al,[esi]
.if ( ( (al=='-') || (al=='+') ) && _zero )
movsb
dec ebx
.endif
.if _zero
mov al,'0'
.else
mov al,32
.endif
rep stosb
.endif
mov ecx,ebx
rep movsb
pop esi
jmp @@top
addfstr: ;special for %f
add ebp,8 ;move to next var.
;copy tempstr to edi based on _*
push esi
mov esi,offset tempstr
.if bptr[esi+1]=='N' || bptr[esi+1]=='I' ;was it NAN or INF?
mov edx,4
mov _zero,0
mov epos,0
mov esiz,0
jmp specialperf
.endif
.if (_pos) && (bptr[esi]!='-')
mov eax,esi
inc eax
callp memcpy,eax,esi,sizeof tempstr - 1
mov bptr[esi],'+'
.endif
call flen ;EBX= whole length ECX=pos of e EDX=size of e
mov epos,ecx
mov esiz,edx
add edx,ebx
add edx,_dec ;6+1 for dec pt
.if _dec ;if _dec is zero then the decimal should not be printed
inc edx ;include the dec pt
.endif
specialperf:
.if edx < _width
mov ecx,_width
sub ecx,edx
mov al,[esi]
.if ( ( (al=='-') || (al=='+') ) && _zero )
movsb
dec edx ;just outputed 1 byte now so do not do it l8r
.endif
.if _zero
mov al,'0'
.else
mov al,' '
.endif
rep stosb
.endif
mov ecx,edx
sub ecx,esiz
rep movsb ;move # first
.if epos ;is there an exp part
mov esi,epos ;move to exp part
mov ecx,esiz
rep movsb
.endif
pop esi
jmp @@top
vsprintf endp
;ret: EBX=whole len ECX=pos of e if exp # (ie: 1e3) else 0 EDX=size of exp part
;in : esi = string
flen proc private uses esi
xor ebx,ebx
xor ecx,ecx
xor edx,edx
lodsb
.while al!='.' && al!='e' && al!=0
inc ebx
lodsb
.endw
.if al==0
ret
.endif
.if al=='e'
jmp e1
.endif
lodsb
.while al!='e' && al!=0
lodsb
.endw
.if al==0
ret
.endif
;exp form detected
e1:
mov ecx,esi
dec ecx
inc edx ;inc for the 'e'
lodsb
.while al!=0
inc edx
lodsb
.endw
ret
flen endp
end